/**
 * @ProjectName: go-learn-demo
 * @PackageName: _2_relation
 * @Description:
 * @Author: hy.bai
 * @Date: 2025-08-05 21:49
 */
package hasmanycrud

import (
	"encoding/json"
	"fmt"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"time"
)

// 获取当前系统时间
var currentTime = time.Now().Format("2006-01-02 15:04:05")

// 定义用户结构体
type User struct {
	gorm.Model
	Username    string        `json:"username" gorm:"column:username"`
	CreditCards []*CreditCard `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"`
	// OnUpdate:CASCADE： 当关联的父表记录被更新时，子表中对应的关联字段会自动同步更新。
	// OnDelete:SET NULL： 当关联的父表记录被删除时，子表中对应的关联字段会被自动设置为NULL。
}

func (*User) TableName() string {
	return "t_user"
}

// 定义信用卡结构体
type CreditCard struct {
	gorm.Model
	Number string `json:"number" gorm:"column:number"`
	UserId uint
}

func (*CreditCard) TableName() string {
	return "t_credit_card"
}

func TasHasManyQuery() {

	dns := "root:root@tcp(127.0.0.1:3308)/test?charset=utf8mb4&parseTime=True&loc=Local"

	gConfig := &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
		DryRun: false,
	}

	db, err := gorm.Open(mysql.Open(dns), gConfig)
	if err != nil {
		panic(fmt.Sprintf("连接数据库失败,失败原因是:%s\n", err.Error()))
	} else {
		fmt.Println(db.Name()) // mysql:表示数据库连接成功
	}

	// 创建表
	// 创建用户表
	user := &User{}
	if !db.Migrator().HasTable(user) {
		db.Debug().Set("gorm:table_options", "comment '用户表'").AutoMigrate(user)
	}

	// 创建信用卡表
	cc := &CreditCard{}
	if !db.Migrator().HasTable(cc) {
		db.Debug().Set("gorm:table_options", "comment '信用卡表'").AutoMigrate(cc)
	}
	// 1.创建一对多
	// CreateUser(db)

	// 2.查询根据主键查询数据
	// findById(db, 1)

	// 3.级联查询
	// findAssociation(db, 2)
	// 4.级联存储
	// saveAssociation(db, 2)

	// 5.预加载
	findPreload(db)

	fmt.Println("数据库初始化执行完毕~~~")
}

// 关联查询
func findAssociation(db *gorm.DB, id uint) {
	// 1.查询主表
	userFormDb := User{
		Model: gorm.Model{
			ID: id,
		},
	}
	db.Debug().First(&userFormDb)
	// 2.进行关联查询
	db.Model(&userFormDb).Association("CreditCards").Find(&userFormDb.CreditCards)
	result, _ := json.Marshal(userFormDb)
	fmt.Printf("查询结果:%s\n", string(result))

}

// 查询集合时，如何进行
func findAllAssociation(db *gorm.DB) {
	// 1.查询主表
	userFormDb := User{
		Model: gorm.Model{
			ID: 1,
		},
	}
	db.Debug().First(&userFormDb)
	// 2.进行关联查询
	db.Model(&userFormDb).Association("CreditCards").Find(&userFormDb.CreditCards)
	result, _ := json.Marshal(userFormDb)
	fmt.Printf("查询结果:%s\n", string(result))
}

// 关联新增
func saveAssociation(db *gorm.DB, id uint) {
	// 1.查询主表
	userFormDb := User{
		Model: gorm.Model{
			ID: id,
		},
	}
	db.Debug().First(&userFormDb)

	// 3.关联新增
	db.Model(&userFormDb).Association("CreditCards").Append( // 也可以Append多个，
		&CreditCard{
			Number: "622848888",
		},
	)

	// 4.关联替换
	// db.Model(&userFormDb).Association("CreditCards").Replace( // 也可以Replace多个
	//	&CreditCard{
	//		//Model: gorm.Model{
	//		//	ID: 1,
	//		//},
	//		Number: "622848888",
	//	},
	// )

	// 2.关联查询
	db.Model(&userFormDb).Association("CreditCards").Find(&userFormDb.CreditCards)
	result, _ := json.Marshal(userFormDb)
	fmt.Printf("查询结果:%s\n", string(result))
}

// 预加载
func findPreload(db *gorm.DB) {
	user := &User{}
	db.Debug().Preload("CreditCards").Find(user)
	result, _ := json.Marshal(user)
	fmt.Printf("查询结果:%s\n", string(result))
}

func findById(db *gorm.DB, id uint) {
	// 根据主键查询数据
	userFormDb := User{
		Model: gorm.Model{
			ID: id,
		},
	}
	db.Debug().First(&userFormDb)
	fmt.Printf("查询结果:%v\n", userFormDb)

	// 注：此时查询出来信用卡的数量
	cards := userFormDb.CreditCards
	fmt.Println("信用卡集合：", len(cards)) // 注:默认情况下不会级联查询
	for i := range cards {
		fmt.Println(cards[i].Number)
	}
}

// 1.创建一对多
func CreateUser(db *gorm.DB) {
	user := &User{
		Username: "abc-" + currentTime,
		CreditCards: []*CreditCard{
			{
				Number: "2025003",
			},
			{
				Number: "2025004",
			},
		},
	}
	db.Create(user)
}
